package com.JUC.cha03.sec04;

import lombok.Getter;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 电商比价
 *
 *
 * 1.需求：
 * 1.1. 同一产品，同时搜索出同款产品在各大电商平台的售价；
 * 1.2. 同一款产品，同时搜索出本产品在同一电商平台下，各个入驻卖家的售价是多少
 * <p>
 * 2. 输出：出来的结果希望是同款产品在不同地方的价格清单列表，返回一个List<String>
 * 2.1. 《mysql》 in jd price is 88.05
 * 2.2. 《mysql》 in dangdang price is 89.12
 * 2.3. 《mysql》 in taobao price is 90.85
 * <p>
 * 3. 技术要求
 * 3.1. 函数式编程
 * 3.2. 链式编程
 * 3.3. Stream流式计算
 */

public class CompletableFutureMallDemo {

    static List<NetMall> list = Arrays.asList(
            new NetMall("jd"),
            new NetMall("dangdang"),
            new NetMall("taobao"),
            new NetMall("pdd"),
            new NetMall("tmall")
    );

    /**
     * List<NetMall> -----> map -----> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPrice(List<NetMall> list, String productName){

        // 《mysql》 in jd price is 88.05
        return list
                .stream()
                .map(netMall ->
                        String.format(productName + " in %s price is %.2f ",
                                netMall.getNetMallName(),
                                netMall.calcPrice(productName)))
                .collect(Collectors.toList());
    }

    /**
     * List<NetMall> -----> List<CompleteFuture<String>> -----> List<String>
     * @param list
     * @param productName
     * @return
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list, String productName){

        // 《mysql》 in jd price is 88.05
        return list.stream().map(netMall ->
                        CompletableFuture.supplyAsync(() -> String.format(productName + " in %s price is %.2f ",// 将list内的集合映射为每个异步任务，放到CompletableFuture异步线程内
                                netMall.getNetMallName(),
                                netMall.calcPrice(productName))))
                // 之后转为Collection.toList()，List<NetMall> -----> List<CompleteFuture<String>>
                .collect(Collectors.toList())
                // List<CompleteFuture<String>> ----> List<String>
                .stream().map(s -> s.join())
                .collect(Collectors.toList());
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        long startTime = System.currentTimeMillis();

        List<String> list1 = getPrice(list, "mysql");
        for (String element : list1) {
            System.out.println(element);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("---- costTime：" + (endTime - startTime) + "毫秒");

        System.out.println("--------------------------------------");

        long startTime2 = System.currentTimeMillis();

        List<String> list2 = getPriceByCompletableFuture(list, "mysql");
        for (String element : list2) {
            System.out.println(element);
        }

        long endTime2 = System.currentTimeMillis();
        System.out.println("---- costTime：" + (endTime2 - startTime2) + "毫秒");

    }
}

class NetMall {

    @Getter
    private String netMallName;

    public NetMall(String netMallName) {
        this.netMallName = netMallName;
    }

    public double calcPrice(String productName){
        // 暂停几秒钟线程
        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }

        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }


}
